const mimeMap = require('./mimeMap.js')

function FormData(){

  let fileManager = wx.getFileSystemManager();

  let data = {};

  let files = [];

  this.append = (name, value)=>{

    data[name] = value;

    return true;

  }

  this.appendFile = (name, path, fileName)=>{

    let buffer = fileManager.readFileSync(path);

    if(Object.prototype.toString.call(buffer).indexOf("ArrayBuffer") < 0){

      return false;

    }

    if(!fileName){

      fileName = getFileNameFromPath(path);

    }

    files.push({

      name: name,

      buffer: buffer,

      fileName: fileName

    });

    return true;

  }

  this.getData = ()=>convert(data, files)

}

function getFileNameFromPath(path){

  let idx=path.lastIndexOf("/");

  return path.substr(idx+1);

}

function convert(data, files){

  let boundaryKey = 'wxmpFormBoundary' + randString(); // 数据分割符，一般是随机的字符串

  let boundary = '--' + boundaryKey;

  let endBoundary = boundary + '--';

  let postArray = [];

  //拼接参数

  if(data && Object.prototype.toString.call(data) == "[object Object]"){

    for(let key in data){

      postArray = postArray.concat(formDataArray(boundary, key, data[key]));

    }

  }

  //拼接文件

  if(files && Object.prototype.toString.call(files) == "[object Array]"){

    for(let i in files){

      let file = files[i];

      postArray = postArray.concat(formDataArray(boundary, file.name, file.buffer, file.fileName));

    }

  }

  //结尾

  let endBoundaryArray = [];

  endBoundaryArray.push(...endBoundary.toUtf8Bytes());

  postArray = postArray.concat(endBoundaryArray);

  return {

    contentType: 'multipart/form-data; boundary=' + boundaryKey,

    buffer: new Uint8Array(postArray).buffer

  }

}

function randString() {

  var result = '';

  var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

  for (var i = 17; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];

  return result;

}

function formDataArray(boundary, name, value, fileName){

  let dataString = '';

  let isFile = !!fileName;

  dataString += boundary + '\r\n';

  dataString += 'Content-Disposition: form-data; name="' + name + '"';

  if (isFile){

    dataString += '; filename="' + fileName + '"' + '\r\n';

    dataString += 'Content-Type: ' + getFileMime(fileName) + '\r\n\r\n';

  }

  else{

    dataString += '\r\n\r\n';

    dataString += value;

  }

  var dataArray = [];

  dataArray.push(...dataString.toUtf8Bytes());

  if (isFile) {

    let fileArray = new Uint8Array(value);

    dataArray = dataArray.concat(Array.prototype.slice.call(fileArray));

  }

  dataArray.push(..."\r".toUtf8Bytes());

  dataArray.push(..."\n".toUtf8Bytes());

  return dataArray;

}

function getFileMime(fileName){

  let idx = fileName.lastIndexOf(".");

  let mime = mimeMap[fileName.substr(idx)];

  return mime?mime:"application/octet-stream"

}

String.prototype.toUtf8Bytes = function(){

  var str = this;

  var bytes = [];

  for (var i = 0; i < str.length; i++) {

    bytes.push(...str.utf8CodeAt(i));

    if (str.codePointAt(i) > 0xffff) {

      i++;

    }

  }

  return bytes;

}

String.prototype.utf8CodeAt = function(i) {

  var str = this;

  var out = [], p = 0;

  var c = str.charCodeAt(i);

  if (c < 128) {

    out[p++] = c;

  } else if (c < 2048) {

    out[p++] = (c >> 6) | 192;

    out[p++] = (c & 63) | 128;

  } else if (

      ((c & 0xFC00) == 0xD800) && (i + 1) < str.length &&

      ((str.charCodeAt(i + 1) & 0xFC00) == 0xDC00)) {

    // Surrogate Pair

    c = 0x10000 + ((c & 0x03FF) << 10) + (str.charCodeAt(++i) & 0x03FF);

    out[p++] = (c >> 18) | 240;

    out[p++] = ((c >> 12) & 63) | 128;

    out[p++] = ((c >> 6) & 63) | 128;

    out[p++] = (c & 63) | 128;

  } else {

    out[p++] = (c >> 12) | 224;

    out[p++] = ((c >> 6) & 63) | 128;

    out[p++] = (c & 63) | 128;

  }

  return out;

};


module.exports = FormData;